# -*- coding: latin-1 -*-

#=========================================================================================
import copy
import os
import subprocess

from PyQt4 import QtCore, QtGui

import Code.Util as Util
import Code.Partida as Partida
import Code.AperturasStd as AperturasStd
import Code.ControlPosicion as ControlPosicion
import Code.Variantes as Variantes

import Code.QT.QTVarios as QTVarios
import Code.QT.QTUtil as QTUtil
import Code.QT.QTUtil2 as QTUtil2
import Code.QT.Colocacion as Colocacion
import Code.QT.Iconos as Iconos
import Code.QT.Controles as Controles

import Code.QT.Tablero as Tablero

import Code.QT.Grid as Grid
import Code.QT.Columnas as Columnas

import Code.QT.FormLayout as FormLayout

#=========================================================================================

def dameApertura( pantalla, configuracion, bloqueApertura, posicApertura ) :
    if bloqueApertura :
        me = QTUtil2.mensEspera.inicio( pantalla, _( "One moment please..." ) )
    w = WAperturas( pantalla, configuracion, bloqueApertura, posicApertura )
    if bloqueApertura :
        me.final()
    if w.exec_() :
        bloqueApertura, posicApertura = w.resultado()
    else :
        bloqueApertura, posicApertura = None, None
    return bloqueApertura, posicApertura

#=========================================================================================
class BLapertura :
    def __init__( self, parent, siPrimera ) :
        #~ self.lb = Controles.LB( "" )
        self.cb = QtGui.QComboBox(  )
        self.cb.setFixedHeight(40)
        self.cb.setFixedWidth(540)
        self.parent = parent
        parent.connect( self.cb, QtCore.SIGNAL("currentIndexChanged(int)"), self.cambiar )
        # ly = Colocacion.V().control( self.cb )#.control( self.lb )
        # self.gb = Controles.GB( None, "", ly )
        self.hija = None
        self.siPrimera = siPrimera
        self.rotulo = _( "Undetermined") if siPrimera else _( "Main line" )
        self.hijos = None
        self.activa = False
        self.numero = 0

    def ponerHija( self, hija ) :
        self.hija = hija

    def iniciar( self, num ) :
        self.cb.setCurrentIndex( num )
        self.cambiar( num )

    def cambiar( self, num ) :
        self.numero = num
        if num <= 0 :
            txt = ""
        else :
            if self.hijos :
                txt = self.hijos[num-1].trPGN()
            else :
                self.activar( False )
        x = "<b>"
        buscaPunto = True
        ant = ""
        for c in txt :
            if buscaPunto :
                if c == "." :
                    x += "</b>"
                    buscaPunto = False
            elif c.isdigit() and ant == " ":
                buscaPunto = True
                x += "<br><b>"
            x += c
            ant = c
        self.cb.setToolTip( x )

        if self.hija :
            if num > 0 :
                bl = self.hijos[num-1]
                self.hija.actualizar( bl.hijos )
            else :
                self.hija.actualizar( None )
        if num <= 0 :
            if self.siPrimera :
                self.parent.ponPartida( None )
        else :
            self.parent.ponPartida( self.hijos[num-1] )

    def actualizar( self, hijos ) :
        self.cb.clear()
        self.hijos = hijos
        if hijos :
            self.cb.addItem( self.rotulo, "" )
            for hijo in hijos :
                txt = hijo.trNombre + "\n      %s"%hijo.trPGN()
                key = hijo.a1h8
                ico = Iconos.Estrella() if hijo.siBasic else Iconos.PuntoNegro()
                self.cb.addItem( ico, txt, key )
            self.activar( True )
        else :
            self.activar( False )
        if self.hija :
            self.hija.actualizar( None )

    def activar( self, siMostrar ) :
        if siMostrar :
            self.activa = True
            # self.gb.show()
            self.cb.show()
        else :
            self.activa = False
            # self.gb.hide()
            self.cb.hide()
            self.numero = -1

#=========================================================================================

#=========================================================================================
class WAperturas( QtGui.QDialog ):

    def __init__( self, wParent, configuracion, bloqueApertura, posicApertura ) :

        super(WAperturas, self).__init__(wParent)

        self.setMaximumWidth( QTUtil.anchoEscritorio() )

        self.apStd = AperturasStd.ListaAperturasStd(configuracion, True, False)
        self.numMovs = 0
        self.posJugada = -1

        self.setWindowFlags( QtCore.Qt.Dialog | QtCore.Qt.WindowTitleHint )

        self.configuracion = configuracion
        self.partida = Partida.Partida()

        self.setWindowTitle( _( "Opening" ) )
        self.setWindowIcon( Iconos.Datos() )

        self.liBL = []
        for i in range( 8 ) :
            self.liBL.append( BLapertura(self, i == 0 ) )
        for i in range( 7 ) :
            self.liBL[i].ponerHija( self.liBL[i+1] )

        # Tablero
        confTablero = configuracion.confTablero( "APERTURAS", 32 )
        self.tablero = Tablero.Tablero(self, confTablero)
        self.tablero.crea()

        # Movimiento
        liAcciones = []
        def x( tit, tr ) :
            liAcciones.append( ( tr, tit, tit ) )

        liAcciones.append( None )
        x( "MoverInicio", _("First move") )
        liAcciones.append( None )
        x( "MoverAtras", _("Previous move") )
        liAcciones.append( None )
        x( "MoverAdelante", _("Next move") )
        liAcciones.append( None )
        x( "MoverFinal", _("Last move") )
        liAcciones.append( None )
        x( "MoverTiempo", _("Timed movement") )
        liAcciones.append( None )

        self.siMoviendoTiempo = False

        lyBM, tbBM = QTVarios.lyBotonesMovimiento( self, "", siLibre = False, tamIcon=24 )
        self.tbBM = tbBM

        # Tool bar
        tb = QTUtil2.creaTBAceptarCancelar( self )

        # Layout

        ## Niveles
        vbox = Colocacion.V()
        for i in range(8) :
            # vbox.control(self.liBL[i].gb)
            vbox.control(self.liBL[i].cb)
        vbox.relleno(1)
        lyD = Colocacion.V().control( tb ).otro( vbox ).margen(3)

        ## Izquierda
        lyI = Colocacion.V().control( self.tablero ).otro( lyBM )

        ## Completo
        ly = Colocacion.H().otro(lyI).otro(lyD).relleno(1).margen(3)
        self.setLayout( ly )

        bl0 = self.liBL[0]
        bl0.actualizar( self.apStd.hijos )
        self.bloqueApertura = bloqueApertura
        if bloqueApertura :
            self.bloqueApertura = self.apStd.dic[bloqueApertura.a1h8]
            if posicApertura :
                for i in range(len(posicApertura)) :
                    bl = self.liBL[i]
                    bl.iniciar( posicApertura[i] )

    #--------------------------------------------------------------------------------------------------------------------------------
    def ponPartida( self, bloqueAp ) :
        self.bloqueApertura = bloqueAp
        self.partida.reset()
        if bloqueAp :
            self.partida.leerPV( bloqueAp.a1h8 )

        self.numJugadas = len(self.partida.liJugadas)
        self.mueve( siFinal = True )
    #--------------------------------------------------------------------------------------------------------------------------------
    def procesarTB( self ) :
        accion = self.sender().clave
        if accion == "aceptar" :
            self.accept()
        elif accion == "cancelar" :
            self.reject()
        elif accion == "MoverAdelante" :
            self.mueve(nSaltar=1)
        elif accion == "MoverAtras" :
            self.mueve(nSaltar=-1)
        elif accion == "MoverInicio" :
            self.mueve(siInicio = True)
        elif accion == "MoverFinal" :
            self.mueve(siFinal = True)
        elif accion == "MoverTiempo" :
            self.mueveTiempo()

    # -----------------------------------------------------------------------------------------------------------------------------------
    def mueve( self, siInicio = False, nSaltar=0, siFinal = False ) :
        if nSaltar :
            pos = self.posJugada + nSaltar
            if pos >= 0 and pos < self.numJugadas :
                self.posJugada = pos
            else :
                return
        elif siInicio :
            self.posJugada = 0
        elif siFinal :
            self.posJugada = self.numJugadas-1
        else :
            return
        if self.numJugadas :
            jg = self.partida.liJugadas[self.posJugada]
            self.tablero.ponPosicion( jg.posicion )
            self.tablero.ponFlechaSC( jg.desde, jg.hasta )
        else :
            self.tablero.ponPosicion( self.partida.iniPosicion )
            self.posJugada = 0
    # -----------------------------------------------------------------------------------------------------------------------------------
    def mueveTiempo( self ) :
        if self.siMoviendoTiempo :
            self.siMoviendoTiempo = False
            self.tiempoOtrosTB( True )
            self.paraReloj()
            return
        def otrosTB( siHabilitar ) :
            for accion in self.tbBM.liAcciones :
                if not accion.clave.endswith("MoverTiempo") :
                    accion.setEnabled( siHabilitar )

        self.tiempoFuncion = self.mueve
        self.tiempoPosMax = self.numJugadas
        self.tiempoPos = 0
        self.tiempoOtrosTB = otrosTB
        self.siMoviendoTiempo = True
        otrosTB( False )
        self.mueve( siInicio = True )
        self.iniciaReloj( self.mueveTiempo1 )

    #-----------------------------------------------------------------------------------
    def mueveTiempo1( self ) :
        self.tiempoPos += 1
        if self.tiempoPos == self.tiempoPosMax :
            self.siMoviendoTiempo = False
            self.tiempoOtrosTB( True )
            self.paraReloj()
            return
        self.tiempoFuncion( nSaltar = 1 )

    #--------------------------------------------------------------------------------------------------------------------------------
    def resultado( self ) :
        resp = []
        for i in range(8) :
            bl = self.liBL[i]
            resp.append( bl.numero )
        return self.bloqueApertura, resp

    #--------------------------------------------------------------------------------------------------------------------------------
    def iniciaReloj( self, funcion ) :
        if not hasattr( self, "timer" ) :
            self.timer = QtCore.QTimer(self)
            self.connect(self.timer, QtCore.SIGNAL("timeout()"), funcion )
        self.timer.start(1000)

    #--------------------------------------------------------------------------------------------------------------------------------
    def paraReloj( self ) :
        if hasattr( self, "timer" )  :
            self.timer.stop()
            delattr( self, "timer" )

#=========================================================================================

#=========================================================================================
class EntrenamientoApertura(QTVarios.WDialogo):
    def __init__(self, owner, listaAperturasStd, dicDatos ) :

        icono = Iconos.Apertura()
        titulo = _("Learn openings by repetition")
        extparam = "opentrainingE"
        QTVarios.WDialogo.__init__(self, owner, titulo, icono, extparam )

        nombre = dicDatos.get( "NOMBRE", "" )
        lista = dicDatos.get( "LISTA", [] )
        self.listaAperturasStd = listaAperturasStd

        tb = QTUtil2.creaTBAceptarCancelar( self )

        lbNombre = Controles.LB( _( "Name" ) + " : ")
        self.edNombre = Controles.ED( self, nombre )

        lyNombre = Colocacion.H().control(lbNombre).control(self.edNombre)

        self.treeView = QtGui.QTreeView()
        self.treeView.setAlternatingRowColors(True)
        self.treeView.setContextMenuPolicy(QtCore.Qt.CustomContextMenu)
        self.treeView.customContextMenuRequested.connect(self.menu)

        self.model = QtGui.QStandardItemModel()
        li, self.dicHijos = self.leer( lista )
        self.treeView.setModel(self.model)

        self.model.setHorizontalHeaderLabels([_("Choose the openings that make this training")])

        layout = Colocacion.V().control(tb).otro(lyNombre).control(self.treeView)

        self.setLayout(layout)

        self.recuperarVideo(siTam=True)

        for item in li :
            self.treeView.scrollTo( item.index() )

    #--------------------------------------------------------------------------------------------------------------------------------
    def procesarTB( self ) :
        getattr( self, self.sender().clave )()

    #--------------------------------------------------------------------------------------------------------------------------------
    def aceptar( self ) :

        self.nombre = self.edNombre.texto().strip()

        if not self.nombre :
            QTUtil2.mensError( self, _("Not indicated the name of training"))
            return

        self.lista = self.listaElegidas()

        if not self.lista :
            QTUtil2.mensError( self, _("you have not indicated any opening"))
            return

        self.guardarVideo()
        self.accept()

    #--------------------------------------------------------------------------------------------------------------------------------
    def cancelar( self ) :
        self.reject()

    #--------------------------------------------------------------------------------------------------------------------------------
    def listaElegidas( self ) :
        lista = []
        def miraHijo( hijo ) :

            if hijo.item.checkState() == QtCore.Qt.Checked :
                lista.append(hijo.a1h8)
            for nieto in hijo.hijos :
                miraHijo( nieto )

        for hijo in self.listaAperturasStd.hijos :
            miraHijo( hijo )

        return lista

    #--------------------------------------------------------------------------------------------------------------------------------
    def leer( self, lista ) :

        li = []
        dic = {}

        def nuevoHijo( padre, hijo, siCheckable ) :
            data = hijo.trNombre + "\n" + hijo.trPGN()
            item = QtGui.QStandardItem( data )
            item.setEditable(False)
            item.setCheckable(siCheckable)
            item.clave = data

            item.nombre = hijo.trNombre

            hijo.item = item
            if hijo.a1h8 in lista :
                item.setCheckState( QtCore.Qt.Checked )
                li.append( item )
            padre.appendRow(item)
            dic[data] = [item]
            for nieto in hijo.hijos :
                nitem = nuevoHijo( item, nieto, True )
                dic[data].append(nitem)
            return item

        for hijo in self.listaAperturasStd.hijos :
            nuevoHijo( self.model, hijo, len(hijo.hijos) == 0  )

        return li, dic

    #--------------------------------------------------------------------------------------------------------------------------------
    def menu( self, position):
        indexes = self.treeView.selectedIndexes()
        if len(indexes) > 0:
            i0 = indexes[0]
            liItems = self.dicHijos[i0.data()]
            if len(liItems) > 1 :
                # itemPadre = liItems[0]

                menu = QTVarios.LCMenu()
                menu_marcar = menu.submenu( _("Mark"), Iconos.PuntoVerde() )
                menu_marcar.opcion( "mt", _( "All"), Iconos.PuntoNaranja() )
                menu_marcar.opcion( "ms", _( "Only next level"), Iconos.PuntoAzul() )

                menu.separador()
                menu_desmarcar = menu.submenu( _("Unmark"), Iconos.PuntoNegro() )
                menu_desmarcar.opcion( "dt", _( "All"), Iconos.PuntoNaranja() )
                menu_desmarcar.opcion( "ds", _( "Only next level"), Iconos.PuntoAzul() )

                resp = menu.lanza()
                if resp :
                    estado = QtCore.Qt.Checked if resp[0] == "m" else QtCore.Qt.Unchecked
                    sitodos = resp[1] == "t"

                    def marca( liItems, sihijos ) :
                        for n, item in enumerate(liItems) : # el primero es el padre
                            if n == 0 :
                                item.setCheckState( estado )
                            else :
                                if sihijos :
                                    liItems = self.dicHijos[item.clave]
                                    marca( liItems, sitodos )

                    marca( liItems, True )

#=========================================================================================
class EntrenamientoAperturas(QTVarios.WDialogo):
    def __init__(self, procesador ) :

        self.procesador = procesador
        self.ficheroDatos = procesador.configuracion.ficheroEntAperturas
        self.ficheroParam = procesador.configuracion.ficheroEntAperturasPar
        self.listaAperturasStd = AperturasStd.ListaAperturasStd(procesador.configuracion, True, True)
        self.lista = []

        owner = procesador.pantalla
        icono = Iconos.Apertura()
        titulo = _("Learn openings by repetition")
        extparam = "opentraining"
        QTVarios.WDialogo.__init__(self, owner, titulo, icono, extparam )

        # Toolbar
        liAcciones = [  ( _( "Quit" ), Iconos.FinPartida(), "terminar" ), None,
                        ( _( "Train" ), Iconos.Entrenar(), "entrenar" ), None,
                        ( _( "New" ), Iconos.TutorialesCrear(), "nuevo" ), None,
                        ( _( "Modify" ), Iconos.Modificar(), "modificar" ), None,
                        ( _( "Remove" ), Iconos.Borrar(), "borrar" ), None,
                        ( _( "Copy" ), Iconos.Copiar(), "copiar" ), None,
                        ( _( "Up" ), Iconos.Arriba(), "arriba" ), None,
                        ( _( "Down" ), Iconos.Abajo(), "abajo" ), None,
                        ( "+"+_( "Openings" ), Iconos.Aperturas(), "masaperturas" ), None,
                        ( _( "Polyglot book" ), Iconos.Libros(), "polyglot" ), None
                    ]
        tb = Controles.TB( self, liAcciones )

        # Lista
        oColumnas = Columnas.ListaColumnas()
        oColumnas.nueva( "NOMBRE", _( "Name" ), 240 )
        oColumnas.nueva( "BLANCAS", _( "White" ), 120, siCentrado = True )
        oColumnas.nueva( "NEGRAS", _( "Black" ), 120, siCentrado = True )
        oColumnas.nueva( "AMBOS", _( "White & Black" ), 120, siCentrado = True )

        self.grid = Grid.Grid( self, oColumnas )
        n = self.grid.anchoColumnas()
        self.grid.setMinimumWidth( n + 20 )
        self.registrarGrid( self.grid )

        # Layout
        layout = Colocacion.V().control(tb).control(self.grid).margen(8)
        self.setLayout( layout )

        self.recuperarVideo(siTam=True)

        self.lista = self.leer()

        self.siReverse = False

    #--------------------------------------------------------------------------------------------------------------------------------
    def procesarTB( self ) :
        getattr( self, self.sender().clave )()

    #--------------------------------------------------------------------------------------------------------------------------------
    def terminar( self ) :
        self.guardarVideo()
        self.reject()
        return

    #--------------------------------------------------------------------------------------------------------------------------------
    def masaperturas( self ) :
        w = AperturasPersonales( self.procesador, self )
        w.exec_()
        self.listaAperturasStd = AperturasStd.ListaAperturasStd(self.procesador.configuracion, True, True)

    #--------------------------------------------------------------------------------------------------------------------------------
    def polyglot( self ) :
        recno = self.grid.recno()
        if recno < 0 :
            return
        reg = self.lista[recno]

        # Pedimos el fichero a generar
        fbin = QTUtil2.salvaFichero( self, _("Polyglot book"), reg["NOMBRE"]+".bin", _("Polyglot book") + " (*.bin)" )
        if not fbin :
            return

        me = QTUtil2.mensEspera.inicio( self, _( "One moment please..." ) )

        # Determinamos el fichero de trabajo
        plTMP = "deleteme_%d.pgn"
        n = 0
        while True :
            fichTMP = plTMP%n
            if Util.existeFichero(fichTMP) :
                n += 1
            else :
                break

        # Creamos el fichero de trabajo
        f = open( fichTMP, "wb" )
        for pv in reg["LISTA"] :
            f.write( '[Result "1/2-1/2"]\n' )
            p = Partida.Partida()
            p.leerPV(pv)
            f.write( p.pgnBase() + " 1/2-1/2\n\n" )
        f.close()

        # Ejecutamos
        li = [ os.path.abspath('engines/polyglot/polyglot.exe'), \
                'make-book', \
                "-pgn", fichTMP, \
                "-bin", fbin, \
                "-max-ply", "99", \
                "-min-game", "1", \
                "-uniform" ]
        Util.borraFichero( fbin )

        process = subprocess.Popen( li, shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)

        me.final()

        # Mostramos el resultado
        txt = process.stdout.read()
        if os.path.isfile( fbin ) :
            txt += "\n" + _X( _("Book created : %1"), fbin )

        QTUtil2.mensaje( self, txt )

        Util.borraFichero( fichTMP )

    #--------------------------------------------------------------------------------------------------------------------------------
    def gridNumDatos( self, grid ) :
        return len(self.lista)

    #--------------------------------------------------------------------------------------------------------------------------------
    def gridDato( self, grid, fila, oColumna ) :
        clave = oColumna.clave
        reg = self.lista[fila]
        if clave == "NOMBRE" :
            return reg["NOMBRE"]

        return "%d"%reg[clave]

    #--------------------------------------------------------------------------------------------------------------------------------
    def entrenar( self, fil=None, col=None ) :
        if len(self.lista) == 0 :
            return
        if fil is None :
            fil = self.grid.recno()

        # Ultimo entrenamiento
        dicPar = Util.recuperaVar( self.ficheroParam )
        if dicPar is None :
            jugamos = "BLANCAS"
            repeticiones = 5
        else :
            jugamos = dicPar["JUGAMOS"]
            repeticiones = dicPar["REPETICIONES"]
        if not ((col is None) or (col.clave == "NOMBRE")) :
            jugamos = col.clave

        # Datos
        liGen = [(None,None)]

        liJ = [ (_( "White" ),"BLANCAS"), (_( "Black" ),"NEGRAS"), (_( "White & Black" ), "AMBOS")  ]
        config = FormLayout.Combobox( _( "Play with" ), liJ )
        liGen.append( ( config, jugamos ) )

        liR = [ ( _("Undefined"), 0 ) ]

        for x in range( 4 ) :
            liR.append( (str(x+1), x+1) )

        for x in range( 5,105, 5 ) :
            liR.append( (str(x), x) )
        config = FormLayout.Combobox( _( "Repetitions" ), liR )
        liGen.append( ( config, repeticiones ) )

        # Editamos
        resultado = FormLayout.fedit( liGen, title=_( "Train" ), parent=self, anchoMinimo=360, icon=Iconos.Entrenar() )
        if resultado is None :
            return

        accion, liResp = resultado
        jugamos = liResp[0]
        repeticiones = liResp[1]

        dicPar = {}
        dicPar["JUGAMOS"] = jugamos
        dicPar["REPETICIONES"] = repeticiones
        Util.guardaVar( self.ficheroParam, dicPar )

        self.resultado = (self.listaAperturasStd, self.ficheroDatos, self.lista, fil, jugamos, repeticiones)
        self.accept()

    #--------------------------------------------------------------------------------------------------------------------------------
    def gridDobleClick( self, grid, fil, col ) :
        self.entrenar( fil, col )

    #--------------------------------------------------------------------------------------------------------------------------------
    def gridDobleClickCabecera( self, grid, oColumna ) :
        clave = oColumna.clave
        if clave != "NOMBRE" :
            return

        li = sorted(self.lista, key=lambda x : x['NOMBRE'].upper() )

        if self.siReverse :
            li.reverse()

        self.siReverse = not self.siReverse

        self.lista = li

        self.grid.refresh()
        self.grid.gotop( )

        self.grabar()

    #--------------------------------------------------------------------------------------------------------------------------------
    def editar( self, fila ) :
        reg = {} if fila is None else self.lista[fila]
        w = EntrenamientoApertura( self, self.listaAperturasStd, reg )
        if w.exec_() :
            reg = {}
            reg["NOMBRE"] = w.nombre
            reg["LISTA"] = w.lista
            reg["BLANCAS"] = 0
            reg["NEGRAS"] = 0
            reg["AMBOS"] = 0

            if fila is None :
                self.lista.append( reg )
                self.grid.gobottom()
            else :
                self.lista[fila] = reg
            self.grid.refresh()
            self.grabar()

    #--------------------------------------------------------------------------------------------------------------------------------
    def nuevo( self ) :
        self.editar( None )

    #--------------------------------------------------------------------------------------------------------------------------------
    def modificar( self ) :
        recno = self.grid.recno()
        if recno >= 0 :
            self.editar( recno )

    #--------------------------------------------------------------------------------------------------------------------------------
    def borrar( self ) :
        fila = self.grid.recno()
        if fila >= 0:
            if QTUtil2.pregunta( self, _X( _("Do you want to delete training %1?"), self.lista[fila]["NOMBRE"] ) ) :
                del self.lista[fila]
                self.grid.refresh()
                self.grabar()

    #--------------------------------------------------------------------------------------------------------------------------------
    def copiar( self ) :
        fila = self.grid.recno()
        if fila >= 0:
            reg = self.lista[fila]
            nreg = copy.deepcopy(reg)
            self.lista.append(nreg)
            self.grid.refresh()
            self.grabar()

    #--------------------------------------------------------------------------------------------------------------------------------
    def leer( self ) :
        lista = Util.recuperaVar( self.ficheroDatos )
        if lista is None :
            lista = []

        return lista

    #--------------------------------------------------------------------------------------------------------------------------------
    def grabar( self ) :
        Util.guardaVar( self.ficheroDatos, self.lista )

    #--------------------------------------------------------------------------------------------------------------------------------
    def arriba( self ) :
        fila = self.grid.recno()
        if fila > 0 :
            self.lista[fila-1],self.lista[fila] = self.lista[fila],self.lista[fila-1]
            self.grid.goto(fila-1,0)
            self.grid.refresh()
            self.grid.setFocus()
            self.grabar()

    #--------------------------------------------------------------------------------------------------------------------------------
    def abajo( self ) :
        fila = self.grid.recno()
        if fila >= 0 and fila < (len(self.lista)-1) :
            self.lista[fila+1],self.lista[fila] = self.lista[fila],self.lista[fila+1]
            self.grid.goto(fila+1,0)
            self.grid.refresh()
            self.grid.setFocus()
            self.grabar()

#=========================================================================================
class AperturasPersonales(QTVarios.WDialogo):
    def __init__(self, procesador, owner = None ) :

        self.procesador = procesador
        self.ficheroDatos = procesador.configuracion.ficheroPersAperturas
        self.lista = []

        if owner is None :
            owner = procesador.pantalla
        icono = Iconos.Apertura()
        titulo = _("Custom openings")
        extparam = "customopen"
        QTVarios.WDialogo.__init__(self, owner, titulo, icono, extparam )

        # Toolbar
        liAcciones = [  ( _( "Quit" ), Iconos.FinPartida(), "terminar" ), None,
                        ( _( "New" ), Iconos.TutorialesCrear(), "nuevo" ), None,
                        ( _( "Modify" ), Iconos.Modificar(), "modificar" ), None,
                        ( _( "Remove" ), Iconos.Borrar(), "borrar" ), None,
                        ( _( "Copy" ), Iconos.Copiar(), "copiar" ), None,
                        ( _( "Up" ), Iconos.Arriba(), "arriba" ), None,
                        ( _( "Down" ), Iconos.Abajo(), "abajo" ), None,
                    ]
        tb = Controles.TB( self, liAcciones )

        # Lista
        oColumnas = Columnas.ListaColumnas()
        oColumnas.nueva( "NOMBRE", _( "Name" ), 240 )
        oColumnas.nueva( "ECO", "ECO", 70, siCentrado = True )
        oColumnas.nueva( "PGN", "PGN", 280 )
        oColumnas.nueva( "ESTANDAR", _( "Add to standard list" ), 120, siCentrado = True )

        self.grid = Grid.Grid( self, oColumnas )
        n = self.grid.anchoColumnas()
        self.grid.setMinimumWidth( n + 20 )
        self.registrarGrid( self.grid )

        # Layout
        layout = Colocacion.V().control(tb).control(self.grid).margen(8)
        self.setLayout( layout )

        self.recuperarVideo(siTam=True)

        self.lista = self.leer()

        self.dicPGNSP = {}

    #--------------------------------------------------------------------------------------------------------------------------------
    def procesarTB( self ) :
        getattr( self, self.sender().clave )()

    #--------------------------------------------------------------------------------------------------------------------------------
    def terminar( self ) :
        self.guardarVideo()
        self.reject()
        return

    #--------------------------------------------------------------------------------------------------------------------------------
    def gridNumDatos( self, grid ) :
        return len(self.lista)

    #--------------------------------------------------------------------------------------------------------------------------------
    def gridDato( self, grid, fila, oColumna ) :
        clave = oColumna.clave
        reg = self.lista[fila]
        if clave == "ESTANDAR" :
            return _("Yes") if reg["ESTANDAR"] else _( "No" )
        elif clave == "PGN" :
            pgn = reg["PGN"]
            if pgn not in self.dicPGNSP :
                p = Partida.Partida()
                p.leerPV(reg["A1H8"])
                self.dicPGNSP[pgn] = p.pgnSP()
            return self.dicPGNSP[pgn]
        return reg[clave]

    #--------------------------------------------------------------------------------------------------------------------------------
    def gridDobleClick( self, grid, fil, col ) :
        self.editar( fil )

    #--------------------------------------------------------------------------------------------------------------------------------
    def gridDobleClickCabecera( self, grid, oColumna ) :
        clave = oColumna.clave

        li = sorted(self.lista, key=lambda x : x[clave].upper() )

        self.lista = li

        self.grid.refresh()
        self.grid.gotop( )

        self.grabar()

    #--------------------------------------------------------------------------------------------------------------------------------
    def editar( self, fila ) :

        if fila is None :
            nombre = ""
            eco = ""
            pgn = ""
            estandar = True
            titulo = _( "New opening" )

        else :
            reg = self.lista[fila]

            nombre = reg["NOMBRE"]
            eco = reg["ECO"]
            pgn = reg["PGN"]
            estandar = reg["ESTANDAR"]

            titulo = nombre

        # Datos
        liGen = [(None,None)]
        liGen.append( ( _( "Name" ) + " :", nombre ) )
        config = FormLayout.Editbox( "ECO", ancho=30, rx = "[A-Z, a-z][0-9][0-9]" )
        liGen.append( (config, eco ) )
        liGen.append( ( _( "Add to standard list" ) + " :", estandar ) )

        # Editamos
        resultado = FormLayout.fedit( liGen, title= titulo, parent = self, anchoMinimo = 460, icon = Iconos.Apertura() )
        if resultado is None :
            return

        accion, liResp = resultado
        nombre = liResp[0].strip()
        if not nombre :
            return
        eco = liResp[1].upper()
        estandar = liResp[2]

        fen = ControlPosicion.FEN_INICIAL

        self.procesador.procesador = self.procesador # ya que editaVariante espera un gestor

        resp = Variantes.editaVariante( self.procesador, fen, pgn, titulo=nombre )

        if resp :
            pgn, a1h8 = resp

            reg =  {}
            reg["NOMBRE"] = nombre
            reg["ECO"] = eco
            reg["PGN"] = pgn
            reg["A1H8"] = a1h8
            reg["ESTANDAR"] = estandar

            if fila is None  :
                self.lista.append( reg )
                self.grid.refresh()
                self.grabar()
            else :
                self.lista[fila] = reg
            self.grid.refresh()
            self.grabar()

    #--------------------------------------------------------------------------------------------------------------------------------
    def nuevo( self ) :
        self.editar( None )

    #--------------------------------------------------------------------------------------------------------------------------------
    def modificar( self ) :
        recno = self.grid.recno()
        if recno >= 0 :
            self.editar( recno )

    #--------------------------------------------------------------------------------------------------------------------------------
    def borrar( self ) :
        fila = self.grid.recno()
        if fila >= 0:
            if QTUtil2.pregunta( self, _X( _("Do you want to delete the opening %1?"), self.lista[fila]["NOMBRE"] ) ) :
                del self.lista[fila]
                self.grid.refresh()
                self.grabar()

    #--------------------------------------------------------------------------------------------------------------------------------
    def copiar( self ) :
        fila = self.grid.recno()
        if fila >= 0:
            reg = self.lista[fila]
            nreg = copy.deepcopy(reg)
            self.lista.append(nreg)
            self.grid.refresh()
            self.grabar()

    #--------------------------------------------------------------------------------------------------------------------------------
    def leer( self ) :
        lista = Util.recuperaVar( self.ficheroDatos )
        if lista is None :
            lista = []

        return lista

    #--------------------------------------------------------------------------------------------------------------------------------
    def grabar( self ) :
        Util.guardaVar( self.ficheroDatos, self.lista )

    #--------------------------------------------------------------------------------------------------------------------------------
    def arriba( self ) :
        fila = self.grid.recno()
        if fila > 0 :
            self.lista[fila-1],self.lista[fila] = self.lista[fila],self.lista[fila-1]
            self.grid.goto(fila-1,0)
            self.grid.refresh()
            self.grid.setFocus()
            self.grabar()

    #--------------------------------------------------------------------------------------------------------------------------------
    def abajo( self ) :
        fila = self.grid.recno()
        if fila >= 0 and fila < (len(self.lista)-1) :
            self.lista[fila+1],self.lista[fila] = self.lista[fila],self.lista[fila+1]
            self.grid.goto(fila+1,0)
            self.grid.refresh()
            self.grid.setFocus()
            self.grabar()
